package com.baiyue.utils;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.regex.Pattern;

/**
 * WEB效用类
 *
 * @author tangfan 2018/8/30 10:28
 */
public class WebUtil {
    private static final Logger logger = LoggerFactory.getLogger(WebUtil.class);

    /**
     * 判断是否为AJAX请求
     *
     * @param request HttpServletRequest
     * @return 是否为AJAX请求
     */
    public static boolean isAjaxRequest(HttpServletRequest request) {
        Assert.notNull(request, "请求不能为null");
        return StringUtils.equalsIgnoreCase(request.getHeader("X-Requested-With"), "XMLHttpRequest");
    }

    public static HttpServletResponse getCurrentResponse() {
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        return response;
    }

    /**
     * 添加cookie
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param name     Cookie名称
     * @param value    Cookie值
     * @param maxAge   有效期(单位: 秒)
     */
    public static void addCookie(HttpServletRequest request, HttpServletResponse response, String name, String value, Integer maxAge) {
        Assert.notNull(request, "请求不能为空");
        Assert.notNull(response, "响应不能为空");
        Assert.hasText(name, "cookie 键名不能为空");
        Assert.hasText(value, "cookie 值不能为空");

        addCookie(request, response, name, value, maxAge, "/", request.getRemoteHost(), null);
    }

    /**
     * 添加cookie
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param name     Cookie名称
     * @param value    Cookie值
     */
    public static void addCookie(HttpServletRequest request, HttpServletResponse response, String name, String value) {
        Assert.notNull(request, "请求不能为空");
        Assert.notNull(response, "响应不能为空");
        Assert.hasText(name, "cookie 键名不能为空");
        Assert.hasText(value, "cookie 值不能为空");

        addCookie(request, response, name, value, null, "/", request.getRemoteHost(), null);
    }

    /**
     * 添加cookie
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param name     Cookie名称
     * @param value    Cookie值
     * @param maxAge   有效期(单位: 秒)
     * @param path     路径
     * @param domain   域
     * @param secure   是否启用加密
     */
    public static void addCookie(HttpServletRequest request, HttpServletResponse response, String name, String value, Integer maxAge, String path, String domain, Boolean secure) {
        Assert.notNull(request, "请求不能为空");
        Assert.notNull(response, "响应不能为空");
        Assert.hasText(name, "cookie 键名不能为空");
        Assert.hasText(value, "cookie 值不能为空");

        try {
            name = URLEncoder.encode(name, "UTF-8");
            value = URLEncoder.encode(value, "UTF-8");
            Cookie cookie = new Cookie(name, value);
            if (maxAge != null) {
                cookie.setMaxAge(maxAge);
            }
            if (StringUtils.isNotEmpty(path)) {
                cookie.setPath(path);
            }
            if (StringUtils.isNotEmpty(domain)) {
                cookie.setDomain(domain);
            }
            if (secure != null) {
                cookie.setSecure(secure);
            }
            response.addCookie(cookie);
            //System.out.println("新增Cookie,name:" + name + ",value:" + value + ",path:" + path + ",domain:" + domain + ",secure:" + secure);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 获取cookie
     *
     * @param request HttpServletRequest
     * @param name    Cookie名称
     * @return Cookie值，若不存在则返回null
     */
    public static String getCookie(HttpServletRequest request, String name) {
        Assert.notNull(request, "请求不能为空");
        Assert.hasText(name, "cookie 键名不能为空");
        //System.out.println("获取Cookie: 需要的name:" + name);
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            try {
                name = URLEncoder.encode(name, "UTF-8");
                for (Cookie cookie : cookies) {
                    if (name.equals(cookie.getName())) {
                        //System.out.println("获取Cookie，成功..");
                        return URLDecoder.decode(cookie.getValue(), "UTF-8");
                    }
                }
            } catch (UnsupportedEncodingException e) {
//                throw new RuntimeException(e.getMessage(), e);
                logger.warn("获取COOKIE失败", e);
                return null;
            }
        }

        //System.out.println("获取Cookie:  null");
        return null;
    }

    /**
     * 获取当前的session令牌
     *
     * @return
     */
    public static String getSession() {
        HttpServletRequest httpServletRequest = getCurrentRequest();
        String session = httpServletRequest.getHeader("Authorization");
        if (StringUtils.isEmpty(session)) {
            session = getCookie(httpServletRequest, "JSESSIONID");
        }
        return session;
    }

    /**
     * 获取机器码
     *
     * @return
     */
    public static String getMachineKey() {
        HttpServletRequest httpServletRequest = getCurrentRequest();
        return httpServletRequest.getHeader("Certified");
    }

    /**
     * 移除cookie
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param name     Cookie名称
     * @param path     路径
     * @param domain   域
     */
    public static void removeCookie(HttpServletRequest request, HttpServletResponse response, String name, String path, String domain) {
        Assert.notNull(request, "请求不能为空");
        Assert.notNull(response, "响应不能为空");
        Assert.hasText(name, "cookie 键名不能为空");

        try {
            name = URLEncoder.encode(name, "UTF-8");
            Cookie cookie = new Cookie(name, null);
            cookie.setMaxAge(0);
            if (StringUtils.isNotEmpty(path)) {
                cookie.setPath(path);
            }
            if (StringUtils.isNotEmpty(domain)) {
                cookie.setDomain(domain);
            }
            response.addCookie(cookie);

            //System.out.println("删除Cookie: name:" + name + ",path:" + path + ",domain:" + domain);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 移除cookie
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @param name     Cookie名称
     */
    public static void removeCookie(HttpServletRequest request, HttpServletResponse response, String name) {
        Assert.notNull(request, "请求不能为空");
        Assert.notNull(response, "响应不能为空");
        Assert.hasText(name, "cookie 键名不能为空");
        removeCookie(request, response, name, "/", request.getRemoteHost());
    }

    /**
     * 获取请求来源
     *
     * @return 请求来源
     */
    public static String getRequestSource() {
        String userAgent = getUserAgent();
        return getMobileOS(userAgent);
    }

    /**
     * 获取用户代理
     *
     * @return
     */
    public static String getUserAgent() {
        HttpServletRequest request = getCurrentRequest();
        String ua = request.getHeader("User-Agent");
        if (StringUtils.isNotEmpty(ua)) {
            return ua.toLowerCase();
        }
        return "";
    }

    /**
     * 获取当前请求
     *
     * @return
     */
    public static HttpServletRequest getCurrentRequest() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return servletRequestAttributes != null ? servletRequestAttributes.getRequest() : null;
    }

    /**
     * 获取使用的手机系统
     *
     * @param userAgent
     * @return
     */
    private static String getMobileOS(String userAgent) {
        String ua = userAgent.toLowerCase();
        if (ua.contains("android")) {
            if (StringUtils.contains(ua, "micromessenger")) {
                return "android:weixin";
            }
            return "android";
        } else if (ua.contains("iphone")) {
            if (StringUtils.contains(ua, "micromessenger")) {
                return "iphone:weixin";
            }
            return "iphone";
        } else {
            return "others";
        }
    }

    /**
     * 判断当前浏览器是否是 和包客户端
     *
     * @return true-为和包客户端
     */
    public static boolean isCmPayClient() {
        String userAgent = getUserAgent();
        return StringUtils.indexOf(userAgent, "cmpay.com") >= 0
                || StringUtils.indexOf(userAgent, "hebao/") >= 0;
    }

    /**
     * 获取远程主机的名称
     *
     * @return
     */
    public static String getHostName() {
        HttpServletRequest request = getCurrentRequest();
        String ip = getIp();
        InetAddress inetAddress;
        try {
            inetAddress = InetAddress.getByAddress(ip.getBytes());
            return inetAddress.getHostName();
        } catch (UnknownHostException e) {
            logger.info("获取远程主机名称失败", e);
        }
        return request.getRemoteHost();
    }

    /**
     * 获取远程IP
     *
     * @return 远程IP
     * @author tangf 2018-07-02 修复可能会出现 ip 为 Null 值的情况
     */
    public static String getIp() {
        HttpServletRequest request = getCurrentRequest();
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (ip.equals("127.0.0.1")) {
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                ip = inet.getHostAddress();
            }
        }
        // 多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        return StringUtils.equals(ip, "0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }

    /**
     * 获取当前域名
     *
     * @return
     */
    public static String getDomain() {
        HttpServletRequest request = getCurrentRequest();
        if (request != null) {
            String url = request.getScheme() + "://" + request.getServerName()
                    + ":" + request.getServerPort();
            return url;
        }
        return "";
    }

    /**
     * 获取当前请求的引用地址
     *
     * @return
     */
    public static String getRequestReferer() {
        HttpServletRequest request = getCurrentRequest();
        return request.getHeader("Referer");
    }

    public static boolean isPhone(String phone) {
        if (org.apache.commons.lang3.StringUtils.isEmpty(phone)) {
            return false;
        }
        String regex = "^1[3|4|5|6|7|8|9][0-9]{9}$";
        return Pattern.compile(regex).matcher(phone).matches();
    }
}
